package com.shchekoldin.juliet.packager.utils;

import com.shchekoldin.juliet.packager.core.Packager;
import com.shchekoldin.juliet.packager.xml.GroupElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class FilesIterator {

    private static final Logger logger = LoggerFactory.getLogger(FilesIterator.class);

    private GroupElement group;

    private String currentFileContent;

    private List<FilesIteratorEvent> onIterate = new ArrayList<FilesIteratorEvent>();

    private List<FilesIteratorEvent> onFinish = new ArrayList<FilesIteratorEvent>();

    private boolean interrupt = false;

    // -------------------------------------------------------
    // -                        LOGIC                        -
    // -------------------------------------------------------

    private void addFilesToList(List<String> filesToAddList, List<String> filesList) {
        for (String fileToAddPath : filesToAddList) {
            addFileToList(fileToAddPath, filesList);
        }
    }

    private void addFileToList(String fileToAddPath, List<String> filesList) {
        boolean isExcluded = (this.group.getExcludeFiles().indexOf(fileToAddPath) != -1);
        boolean isIncluded = (filesList.indexOf(fileToAddPath) != -1);

        if (isExcluded || isIncluded) return;

        filesList.add(fileToAddPath);
    }

    private List<String> prepareFilesToIterateList() {
        FilesFinder filesFinder = FilesFinder.getInstance();
        List<String> result = new ArrayList<String>();

        for (String filePath : this.getGroup().getIncludeFiles()) {
            if (filesFinder.isRegexpPath(filePath)) {
                addFilesToList(filesFinder.findFiles(filePath, this.getGroup().getInputDir()), result);
            } else {
                addFileToList(filePath, result);
            }
        }

        return result;
    }

    private void raiseEvents(List<FilesIteratorEvent> events) {
        for (FilesIteratorEvent event : events) event.run();
    }

    //
    // API
    //

    public FilesIterator(GroupElement group) {
        this.group = group;
    }

    public void run() {
        if (interrupt) return;

        try {
            List<String> filesToIterate = prepareFilesToIterateList();

            for (String currentFilePath : filesToIterate) {
                currentFileContent = FileContentReader.getInstance().run(this.getGroup().getInputDir()
                    + currentFilePath);
                raiseEvents(onIterate);
            }
        } catch (IOException e) {
            logger.error("Can't read file", e);
            Packager.getInstance().exit();
        }

        raiseEvents(onFinish);
    }

    public void interrupt() {
        this.interrupt = true;
    }

    // -------------------------------------------------------
    // -                      GET & SET                      -
    // -------------------------------------------------------

    public String getCurrentFileContent() {
        return currentFileContent;
    }

    public void setCurrentFileContent(String currentFileContent) {
        this.currentFileContent = currentFileContent;
    }

    public GroupElement getGroup() {
        return group;
    }

    public List<FilesIteratorEvent> getOnIterate() {
        return onIterate;
    }

    public List<FilesIteratorEvent> getOnFinish() {
        return onFinish;
    }

}
